#ifndef __INKLUDE_IK_C_THREAD_H__
#define __INKLUDE_IK_C_THREAD_H__


#include <Inklude/Inklude.h>
#include <Windows.h>
#include <functional>
#include <memory>

#define THREAD_LAMBDA_SHRD_PTR std::shared_ptr<Inklude::ikCThreadCodeFragment<void> >
#define BEGIN_IK_THREAD_CODE_VALUE_CAPTURE(pFragment) THREAD_LAMBDA_SHRD_PTR pFragment(new Inklude::ikCThreadCodeFragment<void>([=](){ 
#define BEGIN_IK_THREAD_CODE_REFERENCE_CAPTURE(pFragment) THREAD_LAMBDA_SHRD_PTR pFragment(new Inklude::ikCThreadCodeFragment<void>([&](){ 
#define END_IK_THREAD_CODE }));


namespace Inklude
{
    template < typename ReturnType = void>
    class ikCThreadCodeFragment
    {
    public:
        ikCThreadCodeFragment( std::tr1::function< ReturnType () > lambda );
        virtual bool Execute();
    protected:
    private:
        std::tr1::function<ReturnType ()> _request;
    };

    template < typename ReturnType >
    inline ikCThreadCodeFragment< ReturnType >::ikCThreadCodeFragment( std::function< ReturnType () > lambda )
	    : _request( lambda )
    {
    }

    template < typename ReturnType >
    inline bool ikCThreadCodeFragment< ReturnType >::Execute()
    {
        bool result = false;		
	    try
	    {
            _request();
	    }
	    catch(...)
	    {
	    }
	    result = true;

        return result;
    }


    class INKLUDE_CLASS_EXPORT ikCThread
    {
    public:
	    ikCThread();
        ~ikCThread();
	    bool Start();
	    bool DestroyThread();
	    void RegisterCodeFragement(THREAD_LAMBDA_SHRD_PTR pCodeFragment);
        bool IsRunning();
        static HANDLE RunThread(std::shared_ptr<std::function<void()> > func);

    private:
        bool   m_bRunning;
	    LPVOID m_pParamData;
	    HANDLE m_hThread;
	    DWORD  m_threadId;

        THREAD_LAMBDA_SHRD_PTR m_pCodeFragment;
    };

}  // namespace Inklude



#endif // __INKLUDE_IK_C_THREAD_H__

